/*
 * @author: liubing
 * @Date: 2020-11-29 11:57:54
 * @desc: light.js
 */

//  程序入口, main函数

// shaders
const vs_source = `
attribute vec4 a_Position;
attribute vec4 a_Color;
attribute vec4 a_Normal;
uniform mat4 u_ModelMatrix; //模型矩阵
uniform mat4 u_MvpMatrix;
uniform mat4 u_NormalMatrix;
uniform vec3 u_LightColor; //光的颜色
uniform vec3 u_LightDirection;
uniform vec3 u_LightPosition;   // 点光源
uniform vec3 u_AmbientColor;   // 环境光颜色
uniform vec3 u_AmbientLight;    //环境光颜色
varying vec4 v_Color;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {
    vec4 normal = u_NormalMatrix * a_Normal;
    vec4 vertexPosition = u_ModelMatrix * a_Position;
    gl_Position = u_MvpMatrix * a_Position;
    v_Color = a_Color;
}`;

// const fs_source = `
// precision mediump float;
// varying vec4 v_Color;
// uniform vec4 u_color;
// uniform sampler2D u_Sampler;
// varying vec2 v_TexCoord;
// void main() {
//     gl_FragColor = v_Color;
// }
// `;

const fs_source = `
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_Color;
void main(){
    gl_FragColor = v_Color;
}`;

var device;  //设备接口
var gl;

var plane_vertexBuffer; // 平面的BUFFER
var cube_vertexBuffer; //立方体的buffer
var cube_indexBuffer;
var lightcube_vertexBufferl // 光源立方体的BUFFER



// 初始化环境
function initGL() {
    console.log("initGl() -> ")
    let canvas = document.getElementById("glCanvas");
    gl = canvas.getContext('webgl');
    if(!gl){
        console.log("WebGL Failed");
        return;
    }
    gl.viewport(0, 0, canvas.width, canvas.height)
    console.log("初始化环境成功:  width = %d,height = %d",canvas.width,canvas.height)

    if(!initShaders(gl,vs_source,fs_source)){
        console.log('init shaders failed');
    }
    console.log("gl.program",gl.program);
    // loadShaders();
    // initVertexBuffer();
    setCube();
    gl.enable(gl.DEPTH_TEST);

    var modelMatrix = new Matrix4();  // Model matrix
    var normalMatrix = new Matrix4(); // Transformation matrix for normals
    var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
    normalMatrix.setInverseOf(modelMatrix);
    normalMatrix.transpose();
    gl.uniformMatrix4fv(u_NormalMatrix, false, normalMatrix.elements);

    let u_MvpMatrix = gl.getUniformLocation(gl.program,'u_MvpMatrix');
    if(!u_MvpMatrix){
        console.error("Failed to get location of u_ViewMatrix");
        return;
    }

    let mvpMatrix = new Matrix4()
    mvpMatrix.setPerspective(30,1,1,100);
    mvpMatrix.lookAt(35,35,30 ,0,0,0,0,1,0);

    gl.uniformMatrix4fv(u_MvpMatrix,false,mvpMatrix.elements);

    var normalMatrix = new Matrix4(); // Transformation matrix for normals

}

// 整体循环
function mainLoop() {
    render();
    requestAnimationFrame(mainLoop);
}

// 渲染函数
function render() {
    gl.clearColor(0,0,0,1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    //画平面
    // gl.bindBuffer(gl.ARRAY_BUFFER,plane_vertexBuffer);
    // var a_Position = gl.getAttribLocation(gl.program,'a_Position');
    // gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,0,0);
    // gl.drawArrays(gl.LINES,0,40);

    // gl.bindBuffer(gl.ARRAY_BUFFER, null);
    //画立方体
    
    // gl.bindBuffer(gl.ARRAY_BUFFER,cube_vertexBuffer);
    // a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    // gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 4 * 6, 0);
    // gl.drawArrays(gl.TRIANGLES,0,6);

    // gl.bindBuffer(gl.ARRAY_BUFFER,cube_vertexBuffer);
    
    // let FSIZE = 4
    // a_Position = gl.getAttribLocation(gl.program,'a_Position');
    // if(a_Position < 0){
    //     return -1;
    // }
    // gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,0,0);
    // gl.enableVertexAttribArray(a_Position);
 
    // let a_Color = gl.getAttribLocation(gl.program,'a_Color');
    // if(a_Color < 0){
    //     return -1;
    // }
    // gl.vertexAttribPointer(a_Color,3,gl.FLOAT,false,FSIZE * 6,FSIZE * 3);
    // gl.enableVertexAttribArray(a_Color);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,cube_indexBuffer);
    // // gl.drawArrays(gl.LINES,0,6);
    // gl.drawElements(gl.TRIANGLES,36,gl.UNSIGNED_BYTE,0);
}

// 初始化数据
function initVertexBuffer(){
    console.log("initVertexBuffer() -> ");
    let count = 50;

    // 50 个横线
    let cols = [];
    let rows = [];
    for(i = 0;i < 10; i ++) {
        // cols.push()
        let x1 = -100,y1 = 0,z1= -25 + i * 5;
        let x2 = 100, y2 = 0,z2 = -25 + i * 5;
        cols.push(x1,y1,z1);
        cols.push(x2,y2,z2);

        // rows.push()
        let zz1 = -100,yy1 = 0,xx1 = -25 + i * 5;
        let zz2 = 100,yy2 = 0,xx2 = -25 + i * 5;

        rows.push(xx1,yy1,zz1);
        rows.push(xx2,yy2,zz2);
    }
    console.log(cols)
    // 先画一个平面
    let vertices = new Float32Array(cols.concat(rows))
    let vertexBuffer = gl.createBuffer();
    if(!vertexBuffer){
        console.log("Failed to create the buffer object ");
        return -1;
    }
    gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
    var a_Position = gl.getAttribLocation(gl.program,'a_Position');
    gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,0,0);
    gl.enableVertexAttribArray(a_Position);

    // let a_Color = gl.getAttribLocation(gl.program,'a_Color');
    // gl.vertexAttribPointer(a_Color,)
    plane_vertexBuffer = vertexBuffer
}


function setCube() {

//     let vertices = new Float32Array([
//         2.0, 2.0, 2.0,   
//        -2.0, 2.0, 2.0,  
//        -2.0,-2.0, 2.0,   
//         2.0,-2.0, 2.0,   
//         2.0,-2.0,-2.0,   
//         2.0, 2.0,-2.0,   
//        -2.0, 2.0,-2.0,   
//        -2.0,-2.0,-2.0,   
//    ]);

//    let indices = new Uint8Array([
//        0,1,2, 0,2,3,
//        0,3,4, 0,4,5,
//        0,5,6, 0,6,1,
//        1,6,7, 1,7,2,
//        7,4,3, 7,3,2,
//        4,7,6, 4,6,5,
//    ]);
   
//    let vertexBuffer = gl.createBuffer();
//    let indexBuffer = gl.createBuffer();
//    if(!vertexBuffer || !indexBuffer){
//        console.error("vertexBuffer");
//        return -1;
//    }

//    gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
//    gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);

//    let FSIZE = vertices.BYTES_PER_ELEMENT;
//    console.log("FSIZE -> ",FSIZE);

//    let a_Position = gl.getAttribLocation(gl.program,'a_Position');
//    if(a_Position < 0){
//        return -1;
//    }
//    gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,0,0);
//    gl.enableVertexAttribArray(a_Position);
//    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
//    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);

    var vertices = new Float32Array([
        1.0, 1.0, 1.0,  -1.0, 1.0, 1.0,  -1.0,-1.0, 1.0,   1.0,-1.0, 1.0, // v0-v1-v2-v3 front
        1.0, 1.0, 1.0,   1.0,-1.0, 1.0,   1.0,-1.0,-1.0,   1.0, 1.0,-1.0, // v0-v3-v4-v5 right
        1.0, 1.0, 1.0,   1.0, 1.0,-1.0,  -1.0, 1.0,-1.0,  -1.0, 1.0, 1.0, // v0-v5-v6-v1 up
        -1.0, 1.0, 1.0,  -1.0, 1.0,-1.0,  -1.0,-1.0,-1.0,  -1.0,-1.0, 1.0, // v1-v6-v7-v2 left
        -1.0,-1.0,-1.0,   1.0,-1.0,-1.0,   1.0,-1.0, 1.0,  -1.0,-1.0, 1.0, // v7-v4-v3-v2 down
        1.0,-1.0,-1.0,  -1.0,-1.0,-1.0,  -1.0, 1.0,-1.0,   1.0, 1.0,-1.0  // v4-v7-v6-v5 back
    ]);

    // Colors
    var colors = new Float32Array([
        1, 0, 0,   1, 0, 0,   1, 0, 0,  1, 0, 0,     // v0-v1-v2-v3 front
        0, 1, 0,   0, 1, 0,   0, 1, 0,  0, 1, 0,     // v0-v3-v4-v5 right
        0, 0, 1,   0, 0, 1,   0, 0, 1,  0, 0, 1,     // v0-v5-v6-v1 up
        1, 1, 0,   1, 1, 0,   1, 1, 0,  1, 1, 0,   // v1-v6-v7-v2 left
        1, 0, 1,   1, 0, 1,   1, 0, 1,  1, 0, 1,     // v7-v4-v3-v2 down
        0, 1, 1,   0, 1, 1,   0, 1, 1,  0, 1, 1,　    // v4-v7-v6-v5 back
    ]);

    // Normal
    var normals = new Float32Array([
        0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0,  // v0-v1-v2-v3 front
        1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,  // v0-v3-v4-v5 right
        0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,  // v0-v5-v6-v1 up
        -1.0, 0.0, 0.0,  -1.0, 0.0, 0.0,  -1.0, 0.0, 0.0,  -1.0, 0.0, 0.0,  // v1-v6-v7-v2 left
        0.0,-1.0, 0.0,   0.0,-1.0, 0.0,   0.0,-1.0, 0.0,   0.0,-1.0, 0.0,  // v7-v4-v3-v2 down
        0.0, 0.0,-1.0,   0.0, 0.0,-1.0,   0.0, 0.0,-1.0,   0.0, 0.0,-1.0   // v4-v7-v6-v5 back
    ]);

    // Indices of the vertices
    var indices = new Uint8Array([
        0, 1, 2,   0, 2, 3,    // front
        4, 5, 6,   4, 6, 7,    // right
        8, 9,10,   8,10,11,    // up
        12,13,14,  12,14,15,    // left
        16,17,18,  16,18,19,    // down
        20,21,22,  20,22,23     // back
    ]);

    // Write the vertex property to buffers (coordinates, colors and normals)
    if (!initArrayBuffer(gl, 'a_Position', vertices, 3, gl.FLOAT)) return -1;
    if (!initArrayBuffer(gl, 'a_Color', colors, 3, gl.FLOAT)) return -1;
    if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;

    // Unbind the buffer object
    gl.bindBuffer(gl.ARRAY_BUFFER, null);

    // Write the indices to the buffer object
    var indexBuffer = gl.createBuffer();
    if (!indexBuffer) {
        console.log('Failed to create the buffer object');
        return false;
    }
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);


//    cube_vertexBuffer = vertexBuffer;
   cube_indexBuffer = indexBuffer;

   console.log("length = ",indices.length)
   return indices.length;

}

function initArrayBuffer(gl, attribute, data, num, type) {
    // Create a buffer object
    var buffer = gl.createBuffer();
    if (!buffer) {
      console.log('Failed to create the buffer object');
      return false;
    }
    // Write date into the buffer object
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
    // Assign the buffer object to the attribute variable
    var a_attribute = gl.getAttribLocation(gl.program, attribute);
    if (a_attribute < 0) {
      console.log('Failed to get the storage location of ' + attribute);
      return false;
    }
    gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
    gl.enableVertexAttribArray(a_attribute);
  
    return true;
}


function setLightCube() {

    let vertices = new Float32Array([
        1.0, 1.0, 1.0,   
       -1.0, 1.0, 1.0,  
       -1.0,-1.0, 1.0,   
        1.0,-1.0, 1.0,   
        1.0,-1.0,-1.0,   
        1.0, 1.0,-1.0,   
       -1.0, 1.0,-1.0,   
       -1.0,-1.0,-1.0,   
   ]);

   let indices = new Uint8Array([
       0,1,2, 0,2,3,
       0,3,4, 0,4,5,
       0,5,6, 0,6,1,
       1,6,7, 1,7,2,
       7,4,3, 7,3,2,
       4,7,6, 4,6,5,
   ]);
   
   let vertexBuffer = gl.createBuffer();
   let indexBuffer = gl.createBuffer();
   if(!vertexBuffer || !indexBuffer){
       console.error("vertexBuffer");
       return -1;
   }

   gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
   gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);

   let FSIZE = vertices.BYTES_PER_ELEMENT;
   console.log("FSIZE -> ",FSIZE);

   let a_Position = gl.getAttribLocation(gl.program,'a_Position');
   if(a_Position < 0){
       return -1;
   }
   gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,0,0);
   gl.enableVertexAttribArray(a_Position);
   gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
   gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);


   light_cubeVertexBuffer = vertexBuffer;
   light_cubeIndexBuffer = indexBuffer;

   console.log("length = ",indices.length)
   return indices.length;
}

function initTextures(n) {
    var texture = gl.createTexture();
    var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
    var image = new Image();
    image.onload = function () {
        onLoadTexture(n, texture, u_Sampler, image);
    };
    image.src = "res/image/sky.jpg";
    return true;
}

function onLoadTexture(n, texture, u_Sampler, image) {

    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, texture);

    gl.bindTexture(gl.TEXTURE_2D, texture);// 绑定纹理对象到激活的纹理单元
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);// 纹理放大方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);// 纹理缩小方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);// 纹理水平填充方式
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);// 纹理垂直填充方式
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);

    gl.uniform1i(u_Sampler, 0);

    // gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    // gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
}


function main() {
    // initGL();
    let canvas = document.getElementById("glCanvas");
    const gl = canvas.getContext('webgl');
    if (!gl) {
        console.log("WebGL Failed");
        return;
    }
    console.log("width", canvas.width)
    console.log("height", canvas.height)
    gl.viewport(0, 0, canvas.width, canvas.height)

    if (!initShaders(gl, vs_source, fs_source)) {
        console.error("Failed init Shader");
        return;
    }

    //
    var n = initVertexBuffers(gl);
    if (n < 0) {
        console.log('Failed to set the vertex information');
        return;
    }

    // Set the clear color and enable the depth test
    gl.clearColor(0, 0, 0, 1);
    gl.enable(gl.DEPTH_TEST);

    var u_ModelMatrix = gl.getUniformLocation(gl.program,'u_ModelMatrix');
    var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
    var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
    var u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');
    var u_LightPosition  = gl.getUniformLocation(gl.program, 'u_LightPosition');
    var u_LightColor = gl.getUniformLocation(gl.program,'u_LightColor');
    var u_AmbientLight = gl.getUniformLocation(gl.program,'u_AmbientLight');
    let u_AmbientColor = gl.getUniformLocation(gl.program,'u_AmbientColor');

    mainLoop();
}


function initVertexBuffers(gl){

    var vertices = new Float32Array([
        1.0, 1.0, 1.0,  -1.0, 1.0, 1.0,  -1.0,-1.0, 1.0,   1.0,-1.0, 1.0, // v0-v1-v2-v3 front
        1.0, 1.0, 1.0,   1.0,-1.0, 1.0,   1.0,-1.0,-1.0,   1.0, 1.0,-1.0, // v0-v3-v4-v5 right
        1.0, 1.0, 1.0,   1.0, 1.0,-1.0,  -1.0, 1.0,-1.0,  -1.0, 1.0, 1.0, // v0-v5-v6-v1 up
       -1.0, 1.0, 1.0,  -1.0, 1.0,-1.0,  -1.0,-1.0,-1.0,  -1.0,-1.0, 1.0, // v1-v6-v7-v2 left
       -1.0,-1.0,-1.0,   1.0,-1.0,-1.0,   1.0,-1.0, 1.0,  -1.0,-1.0, 1.0, // v7-v4-v3-v2 down
        1.0,-1.0,-1.0,  -1.0,-1.0,-1.0,  -1.0, 1.0,-1.0,   1.0, 1.0,-1.0  // v4-v7-v6-v5 back
     ]);
   
     // Colors
     var colors = new Float32Array([
       1, 0, 0,   1, 0, 0,   1, 0, 0,  1, 0, 0,     // v0-v1-v2-v3 front
       0, 1, 0,   0, 1, 0,   0, 1, 0,  0, 1, 0,     // v0-v3-v4-v5 right
       0, 0, 1,   0, 0, 1,   0, 0, 1,  0, 0, 1,     // v0-v5-v6-v1 up
       1, 1, 0,   1, 1, 0,   1, 1, 0,  1, 1, 0,   // v1-v6-v7-v2 left
       1, 0, 1,   1, 0, 1,   1, 0, 1,  1, 0, 1,     // v7-v4-v3-v2 down
       0, 1, 1,   0, 1, 1,   0, 1, 1,  0, 1, 1,　    // v4-v7-v6-v5 back
    ]);
   
     // Normal
     var normals = new Float32Array([
       0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0,   0.0, 0.0, 1.0,  // v0-v1-v2-v3 front
       1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,   1.0, 0.0, 0.0,  // v0-v3-v4-v5 right
       0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,   0.0, 1.0, 0.0,  // v0-v5-v6-v1 up
      -1.0, 0.0, 0.0,  -1.0, 0.0, 0.0,  -1.0, 0.0, 0.0,  -1.0, 0.0, 0.0,  // v1-v6-v7-v2 left
       0.0,-1.0, 0.0,   0.0,-1.0, 0.0,   0.0,-1.0, 0.0,   0.0,-1.0, 0.0,  // v7-v4-v3-v2 down
       0.0, 0.0,-1.0,   0.0, 0.0,-1.0,   0.0, 0.0,-1.0,   0.0, 0.0,-1.0   // v4-v7-v6-v5 back
     ]);
   
     // Indices of the vertices
     var indices = new Uint8Array([
        0, 1, 2,   0, 2, 3,    // front
        4, 5, 6,   4, 6, 7,    // right
        8, 9,10,   8,10,11,    // up
       12,13,14,  12,14,15,    // left
       16,17,18,  16,18,19,    // down
       20,21,22,  20,22,23     // back
    ]);
   
     // Write the vertex property to buffers (coordinates, colors and normals)
     if (!initArrayBuffer(gl, 'a_Position', vertices, 3, gl.FLOAT)) return -1;
     if (!initArrayBuffer(gl, 'a_Color', colors, 3, gl.FLOAT)) return -1;
     if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;
   
     // Unbind the buffer object
     gl.bindBuffer(gl.ARRAY_BUFFER, null);
   
     // Write the indices to the buffer object
     var indexBuffer = gl.createBuffer();
     if (!indexBuffer) {
       console.log('Failed to create the buffer object');
       return false;
     }
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
   
     return indices.length;
}

main()